package com.ruoyi.web.controller.inventory;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.InvInventoryTransferDetail;
import com.ruoyi.system.domain.InvReportingLosses;
import com.ruoyi.system.domain.ProductInventory;
import com.ruoyi.system.service.*;
import com.ruoyi.system.util.AbdulEmptyUtils;
import com.ruoyi.system.util.BaseResponse;
import com.ruoyi.system.util.StoreIdUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 库存报损 API 控制器
 *
 * @author ruoyi
 * @date 2025-06-04
 */
@RestController
@RequestMapping("/reportingLosses")
@Api(tags = "库存报损管理")
public class ReportingLossesController {

    @Autowired
    private IReportingLossesService reportingLossesService;

    @Autowired
    private IWarehouseService warehouseService;

    @Autowired
    private IStoreBusinessService storeBusinessService;

    @Autowired
    private StoreIdUtils storeIdUtils;

    @Autowired
    private IInvInventoryTransferDetailService invInventoryTransferDetailService;

    @Autowired
    private IProductInventoryService productInventoryService;

    @PostMapping("/save")
    @ApiOperation("新增库存报损")
    public BaseResponse<Boolean> create(@RequestBody InvReportingLosses reportingLosses) {
        return BaseResponse.success(reportingLossesService.create(reportingLosses));
    }


    @PostMapping("/page")
    @ApiOperation("分页查询库存报损记录")
    public BaseResponse<IPage<InvReportingLosses>> page(@RequestBody InvReportingLosses reportingLosses) {
        LambdaQueryWrapper<InvReportingLosses> lqw = Wrappers.lambdaQuery();
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getId()), InvReportingLosses::getId, reportingLosses.getId());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getReportLossNumber()), InvReportingLosses::getReportLossNumber, reportingLosses.getReportLossNumber());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getWarehouseId()), InvReportingLosses::getWarehouseId, reportingLosses.getWarehouseId());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getStoreId()), InvReportingLosses::getStoreId, reportingLosses.getStoreId());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getIsDelete()), InvReportingLosses::getIsDelete, reportingLosses.getIsDelete());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getIsStatus()), InvReportingLosses::getIsStatus, reportingLosses.getIsStatus());
        lqw.eq(!AbdulEmptyUtils.isEmpty(reportingLosses.getStoreBusinessId()), InvReportingLosses::getStoreBusinessId, reportingLosses.getStoreBusinessId());
        lqw.eq(InvReportingLosses::getStoreId, storeIdUtils.getStoreId());
        if (!AbdulEmptyUtils.isEmpty(reportingLosses.getCreateTimeStart()) && !AbdulEmptyUtils.isEmpty(reportingLosses.getCreateTimeEnd())) {
            lqw.between(InvReportingLosses::getCreateTime, reportingLosses.getCreateTimeStart(), reportingLosses.getCreateTimeEnd());
        }
        if (!AbdulEmptyUtils.isEmpty(reportingLosses.getLossesTimeStart()) && !AbdulEmptyUtils.isEmpty(reportingLosses.getLossesTimeEnd())) {
            lqw.between(InvReportingLosses::getLossesTime, reportingLosses.getLossesTimeStart(), reportingLosses.getLossesTimeEnd());
        }
        Page<InvReportingLosses> page = reportingLossesService.page(new Page<>(reportingLosses.getPageNum(), reportingLosses.getPageSize()), lqw);

        if (AbdulEmptyUtils.isEmpty(page.getRecords())) {
            return BaseResponse.success(page);
        }
        Set<Long> businessIds = new HashSet<>();
        Set<Long> warehouseIds = new HashSet<>();

        for (InvReportingLosses item : page.getRecords()) {
            if (item.getStoreBusinessId() != null) {
                businessIds.add(item.getStoreBusinessId());
            }
            if (item.getWarehouseId() != null) {
                warehouseIds.add(item.getWarehouseId());
            }
        }

        Map<Long, String> warehouseMap = new HashMap<>();
        if (!AbdulEmptyUtils.isEmpty(warehouseIds)) {
            warehouseService.listByIds(warehouseIds).forEach(wh -> warehouseMap.put(wh.getId(), wh.getWarehouseName()));
        }

        Map<Long, String> businessMap = new HashMap<>();
        if (!AbdulEmptyUtils.isEmpty(businessIds)) {
            storeBusinessService.listByIds(businessIds).forEach(sb -> businessMap.put(sb.getId(), sb.getName()));
        }

        for (InvReportingLosses item : page.getRecords()) {
            item.setWarehouseName(warehouseMap.getOrDefault(item.getWarehouseId(), ""));
            item.setStoreBusinessName(businessMap.getOrDefault(item.getStoreBusinessId(), ""));
        }

        return BaseResponse.success(page);
    }


    @GetMapping("/detail")
    @ApiOperation("根据ID查询库存报损记录")
    public BaseResponse<InvReportingLosses> getById(Long id) {
        if (AbdulEmptyUtils.isEmpty(id)) {
            return BaseResponse.error("参数id不能为空");
        }
        InvReportingLosses losses = reportingLossesService.getById(id);
        if (AbdulEmptyUtils.isEmpty(losses)) {
            return BaseResponse.error("此报损记录不存在");
        }
        losses.setWarehouseName(warehouseService.getById(losses.getWarehouseId()).getWarehouseName());
        losses.setStoreBusinessName(storeBusinessService.getById(losses.getStoreBusinessId()).getName());
        LambdaQueryWrapper<InvInventoryTransferDetail> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(InvInventoryTransferDetail::getTransferId, id);
        wrapper.eq(InvInventoryTransferDetail::getStoreId, storeIdUtils.getStoreId());
        wrapper.eq(InvInventoryTransferDetail::getDetailType, 2);
        List<InvInventoryTransferDetail> list = invInventoryTransferDetailService.list(wrapper);
        losses.setDetailList(list);
        return BaseResponse.success(losses);
    }

    @PutMapping("/update")
    @ApiOperation("更新库存报损记录")
    public BaseResponse<Boolean> update(@RequestBody InvReportingLosses reportingLosses) {
        Boolean edit = reportingLossesService.edit(reportingLosses);
        return BaseResponse.success(edit);
    }

    @DeleteMapping("/{id}")
    @ApiOperation("删除库存报损记录")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> delete(@PathVariable Long id) {
        if (AbdulEmptyUtils.isEmpty(id)) {
            return BaseResponse.error("参数ID不能为空");
        }
        InvReportingLosses losses = reportingLossesService.getById(id);
        if (AbdulEmptyUtils.isEmpty(losses)) {
            return BaseResponse.error("此报损记录不存在");
        }
        reportingLossesService.removeById(id);
        LambdaQueryWrapper<InvInventoryTransferDetail> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(InvInventoryTransferDetail::getTransferId, id);
        wrapper.eq(InvInventoryTransferDetail::getDetailType, 2);
        return BaseResponse.success(invInventoryTransferDetailService.remove(wrapper));
    }

    /**
     * 审核
     */
    @GetMapping("/audit")
    @ApiOperation("审核")
    @Transactional(rollbackFor = Exception.class)
    public BaseResponse<Boolean> audit(Long id) {
        if (AbdulEmptyUtils.isEmpty(id)) {
            return BaseResponse.error("参数ID不能为空");
        }
        InvReportingLosses losses = reportingLossesService.getById(id);
        if (AbdulEmptyUtils.isEmpty(losses)) {
            return BaseResponse.error("此报损记录不存在");
        }
        losses.setAuditTime(new Date());
        losses.setIsStatus(2);
        LambdaQueryWrapper<InvInventoryTransferDetail> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(InvInventoryTransferDetail::getTransferId, id);
        wrapper.eq(InvInventoryTransferDetail::getDetailType, 2);
        wrapper.eq(InvInventoryTransferDetail::getStoreId, storeIdUtils.getStoreId());
        List<InvInventoryTransferDetail> list = invInventoryTransferDetailService.list(wrapper);
        Set<Long> productManagementId = list.stream().map(InvInventoryTransferDetail::getProductManagementId).collect(Collectors.toSet());
        LambdaQueryWrapper<ProductInventory> lqw = Wrappers.lambdaQuery();
        lqw.in(ProductInventory::getProductManagementId, productManagementId);
        lqw.eq(ProductInventory::getWarehouseId, losses.getWarehouseId());
        List<ProductInventory> productInventoryList = productInventoryService.list(lqw);
        if (AbdulEmptyUtils.isEmpty(productInventoryList)) {
            return BaseResponse.error("此报损记录不存在");
        }
        Map<Long, ProductInventory> inventoryMap = productInventoryList.stream().collect(Collectors.toMap(ProductInventory::getProductManagementId, e -> e));
        List<ProductInventory> updateList = new ArrayList<>();

        for (InvInventoryTransferDetail detail : list) {
            ProductInventory productInventory = inventoryMap.get(detail.getProductManagementId());
            if (detail.getTransferQuantity() > productInventory.getStockQuantity()) {
                return BaseResponse.error("报损数量不能大于库存数量");
            }
            productInventory.setStockQuantity(productInventory.getStockQuantity() - detail.getTransferQuantity());
            if (productInventory.getStockQuantity() < productInventory.getMinStock()) {
                productInventory.setStockWarning(1);
            }
            if (productInventory.getStockQuantity() >= productInventory.getMaxStock()) {
                productInventory.setStockWarning(2);
            }
            if (productInventory.getStockQuantity() >= productInventory.getMinStock() && productInventory.getStockQuantity() <= productInventory.getMaxStock()) {
                productInventory.setStockWarning(0);
            }
            updateList.add(productInventory);
        }
        productInventoryService.updateBatchById(updateList);
        return BaseResponse.success(reportingLossesService.updateById(losses));
    }
}
